﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Threading.Tasks;
using GodSharp;
using ZK.Common;

namespace ZK.InfraredGrating
{
    /// <summary>
    /// 红外光栅
    /// </summary>
    public class InfraredGrating
    {
        private readonly GodSerialPort _serialPort;
        private bool _isOpened;

        private readonly Action<InfraredGratingPart> _statusChanged;
        /// <summary>
        /// 红外光栅-构造函数
        /// </summary>
        /// <param name="config"></param>
        /// <param name="statusChanged"></param>
        /// <param name="isOk"></param>
        public InfraredGrating(SerialPortConfig config, Action<InfraredGratingPart> statusChanged, Action<bool> isOk)
        {
            _statusChanged = statusChanged;
            AllParts = new Dictionary<byte, InfraredGratingPart>();

            try
            {
                _serialPort =
                new GodSerialPort(config.PortName, config.BaudRate, Parity.None, config.DataBits, StopBits.One)
                {
                    EndCharOfHex = "BB",
                    DataFormat = SerialPortDataFormat.Hex,
                    RtsEnable = true,
                    DtrEnable = true
                };
                _serialPort.UseDataReceived((serialPort, bytes) =>
                {
                    if (bytes.Length != 4)
                    {
                        Console.WriteLine(bytes.Length);
                    }
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        if (bytes[i] == 0xAA && i + 3 < bytes.Length && bytes[i + 3] == 0xBB)
                        {
                            var part = new InfraredGratingPart
                            {
                                Address = bytes[i + 1],
                                Status = (InfraredGratingStatus)bytes[i + 2],
                                LastUpdateTime = DateTime.Now
                            };
                            if (AllParts.ContainsKey(part.Address))
                            {
                                AllParts[part.Address] = part;
                            }
                            else
                            {
                                AllParts.Add(part.Address, part);
                            }
                            _statusChanged?.Invoke(part);
                            isOk?.Invoke(AllParts.All(x => x.Value.Status == InfraredGratingStatus.未遮挡));
                        }
                    }
                });
                Open();
            }
            catch (Exception ex)
            {
                Common.Log4.LogManage.WriteErr(ex.ToString());
            }
        }
        /// <summary>
        /// 打开
        /// </summary>
        public void Open()
        {
            _isOpened = _serialPort.Open();
            ReopenIfClosed();
        }
        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            _isOpened = !_serialPort.Close();
        }

        public Dictionary<byte, InfraredGratingPart> AllParts { get; set; }
        /// <summary>
        /// 重启
        /// </summary>
        private  void ReopenIfClosed()
        {
            if (_isOpened)
            {
                try
                {
                    foreach (var part in AllParts.Values)
                    {
                        if (part.LastUpdateTime.HasValue && part.LastUpdateTime < DateTime.Now.AddSeconds(-10))
                        {
                            part.Status = InfraredGratingStatus.设备异常;
                            _statusChanged?.Invoke(part);
                        }
                    }
                }
                catch (Exception ex) { }
                // Task.Delay(1000);
                // Task.Run(() =>
                //{
                //    if (!_serialPort.IsOpen)
                //    {
                //        _serialPort.Close();
                //        _serialPort.Open();
                //    }
                //    ReopenIfClosed();
                //});
            }
            else
            {
                _serialPort.Close();
            }
        }
    }
}
